#!/usr/bin/env perl
# vim: set expandtab shiftwidth=2 tabstop=2:
use 5.14.0;
use strict;
use warnings;
use LWP::Simple qw(get);
use Text::Xslate;
use Log::Minimal qw(infof);

my $SPEC = "http://www.unicode.org/reports/tr11/";
my $DATA = "http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt";

my %params = (
    spec_uri => $SPEC,
    data_uri => $DATA,

    F  => [],
    W  => [],
    H  => [],
    N  => [],
    Na => [],
    A  => [],
);

infof 'get data from %s', $DATA;
my $data = get($DATA);

my($version) = $data =~ /EastAsianWidth-([\d\.]+)\.txt/;
$params{version} = $version;

infof 'parse character tratis';
my @traits;
for my $line(split /\n/, $data) {
    $line =~ s/\#.*//;
    if ($line =~ m{ (?<code_first> \w+) \.\.(?<code_last> \w+) ; (?<trait> \w+) }xms) {
        for my $code(hex($+{code_first}) .. hex($+{code_last})) {
            $traits[$code] = $+{trait};
        }
    }
    elsif ($line =~ m{ (?<code> \w+) ; (?<trait> \w+) }xms) {
        $traits[hex $+{code}] = $+{trait};
    }
}
infof 'make ranges from traits';

my $c    = 0;
my $trait = "";
my $first = -1;
foreach my $t(@traits) {
    next unless $t;

    if ($t ne $trait) {
        if ($trait ne "" && $first != -1) {
            push $params{$trait}, [ $first, $c - 1 ];
        }

        $first = $c;
        $trait = $t;
    }
}
continue {
    ++$c;
}

infof 'render it';

my $xslate = Text::Xslate->new(
    type  => "text",
    cache => 0,
    type  => 'text',
    module => ['Text::Xslate::Bridge::Star'],
);

print $xslate->render_string(do {
        local $/;
        <DATA>;
    }, \%params);

__DATA__
# THIS FILE IS AUTOMATICALLY GENERATED.
# DO NOT EDIT IT!
#
# Unicode version <: $version :> of EastAsianWidth characters
#
# see <: $spec_uri :> for specification
# see <: $data_uri :> for data

module VisualWidth
<:-
macro range -> $r {
    if $r[0] == $r[1] {
        sprintf('\u{%04X}', $r[0]);
    }
    else {
        sprintf('\u{%04X}-\u{%04X}', $r[0], $r[1]);
    }
}
-:>
: macro make_conditions -> $t, $name {
  <: $name :> = '[' +
    : for $t -> $range {
    '<: range($range) :>' +
    : }
    ']'
: }

  : make_conditions($W, "Wide");

  : make_conditions($F, "Fullwide");

  : make_conditions($A, "Ambiguous");
end

